package com.sscl.baselibrary.files

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.ContentUris
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import androidx.core.content.FileProvider
import com.sscl.baselibrary.provider.AutoInitProvider
import java.io.File

/**
 * FileProvider工具类
 *
 * @author ALM
 */
@Suppress("unused")
object FileProviderUtil : FileProvider() {

    /*--------------------------------静态常量--------------------------------*/

    private const val CONTENT_CONTENT = "content"
    private const val ROOT_PATH = "/root"

    /*--------------------------------公开静态方法--------------------------------*/

    /**
     * 根据File获取文件Uri
     *
     * @param context 上下文
     * @param file    File对象
     * @return 文件Uri
     */
    fun getUriFromFile(context: Context, file: File): Uri {
        val fileUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            getUriFromFile24(context, file)
        } else {
            Uri.fromFile(file)
        }
        return fileUri
    }

    /**
     * 设置intent数据和type
     *
     * @param context  上下文
     * @param intent   Intent
     * @param type     type
     * @param file     文件
     * @param canWrite 是否可写
     */
    fun setIntentDataAndType(
        context: Context,
        intent: Intent,
        type: String,
        file: File,
        canWrite: Boolean
    ) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setDataAndType(getUriFromFile24(context, file), type)
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            if (canWrite) {
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            }
        } else {
            intent.setDataAndType(Uri.fromFile(file), type)
        }
    }

    /**
     * 设置intent数据
     *
     * @param context  上下文
     * @param intent   intent
     * @param file     文件
     * @param canWrite 是否可写
     */
    fun setIntentData(context: Context, intent: Intent, file: File, canWrite: Boolean) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.data = getUriFromFile24(context, file)
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            if (canWrite) {
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            }
        } else {
            intent.data = Uri.fromFile(file)
        }
    }

    /**
     * 加入权限
     *
     * @param context  上下文
     * @param intent   intent
     * @param uri      文件Uri
     * @param canWrite 是否可写
     */
    @SuppressLint("QueryPermissionsNeeded")
    fun grantPermissions(context: Context, intent: Intent, uri: Uri, canWrite: Boolean) {
        var flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
        if (canWrite) {
            flag = flag or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        }
        intent.addFlags(flag)
        val resInfoList =
            context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
        for (resolveInfo in resInfoList) {
            val packageName = resolveInfo.activityInfo.packageName
            context.grantUriPermission(packageName, uri, flag)
        }
    }

//    /**
//     * 根据文件Uri获取文件路径
//     *
//     * @param uri 文件Uri
//     * @return 文件路径
//     */
//    fun getPath(uri: Uri): String {
//        //根据文件Uri获取文件路径
//
//
////        val scheme = uri.scheme
////        if (CONTENT_CONTENT != scheme) {
////            throw RuntimeException("Uri scheme error! Need $CONTENT_CONTENT,find $scheme.")
////        }
////        if (!uri.isAbsolute) {
////            throw RuntimeException("Uri must be absolute")
////        }
////        var path = uri.path ?: return ""
////        if (path.startsWith(ROOT_PATH)) {
////            path = path.substring(ROOT_PATH.length)
////        }
////        return path
//    }

    /**
     * 根据文件Uri获取文件路径
     *
     * @param context 上下文
     * @param uri 文件Uri
     * @return 文件路径
     */
    @SuppressLint("NewApi")
    fun getPath(uri: Uri): String? {
        val context = AutoInitProvider.context ?: return null
        // 首先判断是否为Android 4.4及以上版本
        if (DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                if ("primary".equals(type, ignoreCase = true)) {
                    return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                }
                // 其他存储设备，这里可以添加更多处理逻辑
            } else if (isDownloadsDocument(uri)) {
                // DownloadsProvider
                val id = DocumentsContract.getDocumentId(uri)
                val contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)
                )
                return getDataColumn(context, contentUri, null, null)
            } else if (isMediaDocument(uri)) {
                // MediaProvider
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                var contentUri: Uri? = null
                when (type) {
                    "image" -> contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                    "video" -> contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                    "audio" -> contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }
                val selection = "_id=?"
                val selectionArgs = arrayOf(split[1])
                return getDataColumn(context, contentUri, selection, selectionArgs)
            }
        } else if ("content".equals(uri.scheme, ignoreCase = true)) {
            // 普通的ContentProvider类型的Uri
            return getDataColumn(context, uri, null, null)
        } else if ("file".equals(uri.scheme, ignoreCase = true)) {
            // 文件类型的Uri
            return uri.path
        }
        return null
    }

    /*--------------------------------私有静态方法--------------------------------*/

    /**
     * 获取数据列的值
     *
     * @param context 上下文
     * @param uri 内容Uri
     * @param selection 查询条件
     * @param selectionArgs 查询条件参数
     * @return 数据列的值
     */
    private fun getDataColumn(
        context: Context, uri: Uri?, selection: String?,
        selectionArgs: Array<String>?
    ): String? {
        var cursor: Cursor? = null
        val column = "_data"
        val projection = arrayOf(column)
        try {
            cursor = context.contentResolver.query(
                uri!!, projection, selection, selectionArgs,
                null
            )
            if (cursor != null && cursor.moveToFirst()) {
                val index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(index)
            }
        } finally {
            cursor?.close()
        }
        return null
    }

    /**
     * 判断是否为外部存储文档
     *
     * @param uri 文件Uri
     * @return 是否为外部存储文档
     */
    private fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    /**
     * 判断是否为下载文档
     *
     * @param uri 文件Uri
     * @return 是否为下载文档
     */
    private fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    /**
     * 判断是否为媒体文档
     *
     * @param uri 文件Uri
     * @return 是否为媒体文档
     */
    private fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }

    /**
     * 根据File获取文件Uri（需要至少API24）
     *
     * @param context 上下文
     * @param file    File对象
     * @return 文件Uri
     */
    @TargetApi(Build.VERSION_CODES.N)
    private fun getUriFromFile24(context: Context, file: File): Uri {
        val authority = context.packageName + ".fileprovider"
        return getUriForFile(context, authority, file)
    }
}